package com.chisheng.caa.service;

import com.chisheng.caa.exception.ValueNotFoundException;
import com.chisheng.caa.pojo.Bean;
import com.chisheng.caa.util.BeanUtil;
import com.chisheng.caa.util.MapUtil;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class AbstractCRUD<T extends Bean> implements CRUD<T> {

    protected final CacheUtil cacheUtil;

    public AbstractCRUD(CacheUtil cacheUtil) {
        this.cacheUtil = Objects.requireNonNull(cacheUtil);
    }

    @Override
    public void add(String accessKey, T t) {
        State<T> state = cacheUtil.checkAndGet(accessKey);
        MapUtil.put(state.getData(), t, getDuplicateStrategy(accessKey));
    }

    @Override
    public void remove(String accessKey, String id) {
        State<T> state = cacheUtil.checkAndGet(accessKey);
        state.getData().remove(id);
    }

    @Override
    public void modify(String accessKey, T t) {
        State<T> state = cacheUtil.checkAndGet(accessKey);
        Map<String, T> data = state.getData();
        if (!data.containsKey(t.getKey())) {
            throw new ValueNotFoundException(String.format("数据 '%s' 不存在", t.getKey()));
        }

        T dest = data.get(t.getKey());
        BeanUtil.copyProperties(t, dest, true);
    }

    @Override
    public T getOne(String accessKey, String id) {
        State<T> state = cacheUtil.checkAndGet(accessKey);
        return state.getData().get(id);
    }

    @Override
    public Collection<T> getCollection(String accessKey) {
        State<T> state = cacheUtil.checkAndGet(accessKey);
        return state.getData().values();
    }

    public static class AbstractState<E extends Bean> implements State<E> {

        protected Map<String, E> data;

        @Override
        public Map<String, E> getData() {
            return data;
        }

        @Override
        public void setData(Map<String, ? extends E> data) {
            this.data = new HashMap<>(data);
        }

    }

}
